xen/serial: setup UART idle mode for OMAP
authorOleksandr Dmytryshyn <oleksandr.dmytryshyn@globallogic.com>
Mon, 8 Dec 2014 13:51:47 +0000 (15:51 +0200)
committerIan Campbell <ian.campbell@citrix.com>
Tue, 16 Dec 2014 12:41:06 +0000 (12:41 +0000)
The UART is not able to receive bytes when idle mode is not configured
properly, therefore setup the UART with autoidle and wakeup enabled.

Older Linux kernels (for example 3.8) configure hwmods for all devices
even if the device tree nodes for those devices is absent in device
tree, thus UART idle mode is configured too.  With such kernels we can
workaround the issue by adding a fake node in the UART containing this
MMIO range, which is therefore mapped by Xen to dom0, which
reconfigures the UART, causing things to work normally.

Newer Linux Kernels (3.12 and beyond) do not configure idle mode for
UART and so this hack no longer works.

Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytryshyn@globallogic.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
[ ijc -- updated commit message as discussed ]

xen/drivers/char/omap-uart.c
xen/include/xen/8250-uart.h

index a798b8df2f642565eb012c622da5a9d20be53692..16d1454fb413194cd78917a771fa96034c721001 100644 (file)
@@ -195,6 +195,9 @@ static void __init omap_uart_init_preirq(struct serial_port *port)
     omap_write(uart, UART_MCR, UART_MCR_DTR|UART_MCR_RTS);
 
     omap_write(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+
+    /* setup iddle mode */
+    omap_write(uart, UART_SYSC, OMAP_UART_SYSC_DEF_CONF);
 }
 
 static void __init omap_uart_init_postirq(struct serial_port *port)
index a682bae797c6e53edd85ab91dd5fdd024d62f226..304b9dd98de5dea0e88740ec090dea1b55b44692 100644 (file)
@@ -32,6 +32,7 @@
 #define UART_MCR          0x04    /* Modem control        */
 #define UART_LSR          0x05    /* line status          */
 #define UART_MSR          0x06    /* Modem status         */
+#define UART_SYSC         0x15    /* System configuration register */
 #define UART_USR          0x1f    /* Status register (DW) */
 #define UART_DLL          0x00    /* divisor latch (ls) (DLAB=1) */
 #define UART_DLM          0x01    /* divisor latch (ms) (DLAB=1) */
 /* SCR register bitmasks */
 #define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK (1 << 7)
 
+/* System configuration register */
+#define OMAP_UART_SYSC_DEF_CONF 0x0d /* autoidle mode, wakeup is enabled */
+
 #endif /* __XEN_8250_UART_H__ */
 
 /*